<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace app\api\controller\v1;

use app\api\controller\Basic;
use app\common\model\MemberMiniapp;
use app\common\model\User as ModelUser;
use buwang\exception\MiniappException;
use buwang\facade\WechatMp as Mp;
use app\common\model\Sms;
use buwang\service\UserService;
use buwang\util\bytedance\Ttlib;
use buwang\util\ReCaptcha;
use filter\Inspect;
use buwang\util\bytedance\Ttapp;

/**
 * h5 official app pc端的公共方法
 */
class App extends Basic
{
    // 初始化
    protected function initialize()
    {
        parent::initialize();
        //租户后台和运营平台后台不会走这里，走的终端【['app', 'official', 'h5', 'pc', 'tt']】
        if (in_array($this->request->scopes(), ['member', 'admin'])) {
            cookie('token',null);
            throw new MiniappException('用户来源scopes错误！，请刷新页面重试');
        }
        if (!in_array($this->request->scopes(), ['app', 'official', 'h5', 'pc', 'tt'])) throw new MiniappException('登录用户来源scopes错误！');
    }

    /**
     * 通用注册接口
     */
    public function commonReg()
    {
        if ($this->request->isPost()) {
            $data = [
                'mobile' => $this->request->param('mobile/s'),
                'password' => $this->request->param('password/s'),
                'code' => $this->request->param('code/s'),//手机号验证码
                'invite_code' => $this->request->param('invite_code/s', ''),//用户推荐码
            ];
            if($this->request->scopes() === 'pc') {
                validate(\buwang\validate\User::class)->scene('userRegPc')->check($data);
            } else {
                validate(\buwang\validate\User::class)->scene('userReg')->check($data);
            }
            if(!Sms::check($data['mobile'], $data['code'], 'user_register')) return $this->error(Sms::getError());
            //NOTE 需要验证验证码
            $res = ModelUser::where('member_miniapp_id', $this->app_id)->where('mobile', $data['mobile'])->find();
            if ($res) return $this->error('手机号已经被注册');
            //出入用户
            $insert_data = [
                'username' => 'bw' . $data['mobile'],
                'nickname' => 'bw' . $data['mobile'],//TODO 2021/5/20 用户增加默认昵称
                'mobile' => $data['mobile'],
                'password' => password_hash(md5($data['password']), PASSWORD_DEFAULT),
                'status' => 1,
                'member_miniapp_id' => $this->app_id,
//                'avatar'=>bw_img_url('/static/manage/images/default_user_head.png'),//TODO 2021/5/20 用户无头像增加默认头像
                'create_time' => time(),
            ];

            $is_invite = $data['invite_code'] ? ModelUser::isInvite($data['invite_code']) : false;  //查邀请码是否有效
            if ($is_invite) {
                $insert_data['pid'] = de_code($data['invite_code']);//注册用户加入上级推荐人
            }
            $last_id = ModelUser::insertGetId($insert_data);
            if (!$last_id) return $this->error('注册失败');
                ModelUser::where('id', $last_id)->data(['invite_code' => en_code($last_id)])->update();//每个人的邀请码是根据ID生成的可解密code
            $result = ModelUser::find($last_id);
            //用户注册成功后事件
            event('UserRegisterSuccess', [$result, $this->request->scopes()]);
            //确认通过后最后清除验证码
            Sms::clear($data['mobile'],'register');
            return $this->success('注册成功', $result);

        } else {
            return $this->error('request method error');
        }
    }

    /**
     * 通用登录接口
     * @return \think\Response
     */
    public function commonLogin()
    {
        if ($this->request->isPost()) {
            $data = [
                'mobile' => $this->request->param('mobile/s', ''),
                'password' => $this->request->param('password/s', ''),
                'captcha' => $this->request->param('captcha/s', ''),//TP动态验证码
                'uuid' => $this->request->param('uuid/s', ''),//用于验证动态验证码
            ];
            if($this->request->scopes() === 'pc') {
                //var_dump($this->app_id);die;
                $config = app('config');
                $session = app('session');
                if(!(new ReCaptcha($config,$session))->check($data['captcha'],$data['uuid'])){
                    // 验证失败
                    return $this->error('验证码验证失败！');
                };
                validate(\buwang\validate\User::class)->scene('userLogin')->check($data);
            } else {
                validate(\buwang\validate\User::class)->scene('userLogin')->check($data);
            }
            //验证密码是否正确
            $retData = UserService::validateUser($data['mobile'], $data['password'], $this->app_id);
            $userInfo = $retData['rs'];
            if (!$userInfo) return $this->error($retData['error']);
            $rs = UserService::loginUser($userInfo, $this->scopes, true);
            if (!$rs['rs']) return $this->error($rs['error']);
            $return_data = $rs['rs'];
            $return_data['uid'] = $userInfo['id'];
            $return_data['invite_code'] = $userInfo['invite_code'];//获取小程序用户的邀请码
            $return_data['session_id'] = get_session_id();//通用函数定义
            return $this->success('登陆成功', $return_data);
        } else {
            return $this->error('request method error');
        }
    }

    /**
     * 获取公众号JSSDK配置
     */
    public function getJSSDK()
    {
        $app = $this->app_id;
        $config = Mp::jsApiList($app, ['hideAllNonBaseMenuItem', "getNetworkType", 'chooseWXPay']);
        return $this->success('获取公众号配置成功！', $config);
    }
    /**
     * API方式获取重写的tp验证码和session_id
     */
    public function getVerify(): \think\Response
    {
        $config = app('config');
        $session = app('session');
        return $this->success('成功',[
            'session_key'=>\think\facade\Session::getId(),  //cookie
            'img_src' => (new ReCaptcha($config,$session))->create(null, true)->getData(),
        ]);
    }

    /**
     *  公众号微信授权登录API
     */
    public function officialLogin(): \think\Response
    {
        $app = $this->app_id;//应用id
        if (!$app) return $this->error("解析service_id对应应用信息失败");
        $open_id = $this->request->param('open_id'); //授权code
        $mobile = $this->request->param('mobile/s','');//手机号
        $invite_code = $this->request->param('invite_code/s');//推荐码
        $validate_code = $this->request->param('validate_code/s'); //验证码
        $code = $this->request->param('code'); //授权code
        if (empty($open_id) && empty($code)) {
            return $this->error('参数错误，关键参数不能为空');
        }
        //判断是否开放平台应用
        $miniapp = MemberMiniapp::where(['id' => $app])->find();
        if (!$miniapp) {
            return $this->error('未找到已授权应用');
        }

        $official = Mp::getWechatObj($app);
        if (!$official) {
            return $this->error('请先授权您的公众号');
        }
        $data['mobile'] = '';
        if ($mobile) {
            //手机号验证码
            if (!Sms::check($mobile, $validate_code, 'bind_mobile')) return $this->error('验证码错误');
            $data['mobile'] = $mobile;
        }

        if($open_id){
            $rel = $official->user->get($open_id);
            $data['unionid'] = empty($rel['unionid']) ? '' : $rel['unionid'];
            $data['official_uid'] = $rel['openid'];
            $nickName = Inspect::filter_Emoji($rel['nickname']);
            $data['avatar'] = $rel['headimgurl'];
        }else{
            $rel = $official->oauth->user();
            $original = $rel->getOriginal();//微信返回原始数据
            $data['unionid'] = empty($original['unionid']) ? '' : $original['unionid'];
            $data['official_uid'] = $rel->getId();
            $nickName = Inspect::filter_Emoji($rel->getName());
            $data['avatar'] = $rel->getAvatar();
        }

        $data['miniapp_id'] = $app;//MemberMiniapp表id
        $data['miniapp_uid'] = '';
        $data['session_key'] = '';
        $data['nickname'] = $nickName ?? 'WX-' . time();

        $data['invite_code'] = $invite_code;//后面添加推荐人用到
        $uid = ModelUser::wechatReg($data, 'official');//注册新用户或者更新用户信息
        if (!$uid) {
            if (ModelUser::getErrorCode() == 400832) {
                //缺少手机号需要重新变更手机号
                $auth = [];
                $auth_data = [];
                $auth['open_id'] = $data['official_uid'];
                $auth['nickname'] = $nickName ?? 'WX-' . time();
                $auth['avatar'] = $data['avatar'];
                $auth['invite_code'] = $invite_code;//后面添加推荐人用到
                $auth_data['user_info'] = $auth;  //应用信息
                $auth_data['type'] = 'official';  //应用信息
                return $this->code(200)->error(ModelUser::getError(), $auth_data, ModelUser::getErrorCode());
            } else {
                return $this->code(200)->error('用户认证失败！');
            }
        }
        $userInfo = ModelUser::find($uid);//得到登录用户信息
        //调用用户登录
        $rs = UserService::loginUser($userInfo, 'official', true);
        if (!$rs['rs']) return $this->error($rs['error']);
        if ($data['mobile']) Sms::clear($data['mobile'], 'bind_mobile');
        $return_data = $rs['rs'];//登录成功token信息
        $return_data['uid'] = $uid;  //用户信息
        $return_data['invite_code'] = $userInfo['invite_code'];//获取小程序用户的邀请码
        $return_data['session_id'] = get_session_id();//返回登录session
        return $this->success('登录成功', $return_data);
    }
    /**
     * 头条系小程序登录及用户自动注册逻辑
     * @return \think\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function ttLogin()
    {
        $app = $this->app_id;//应用id
        $scopes = $this->scopes;//应用id
        if (!$app || $scopes !== 'tt') return $this->error("解析header对应应用信息失败");
        if($this->request->isPost()){
            $data = [
                'mobile' => $this->request->param('mobile/s', ''),
                'user_info' => $this->request->param('user_info/s', ''),
                'mobile_code' => $this->request->param('mobile_code/d', ''),
                'invite_code' => $this->request->param('invite_code/s', ''),//用户推荐码
                'code' => $this->request->param('code/s', ''),//头条授权
            ];
            if (!$data['code']) return $this->error('授权code不能为空');
            if(!$data['user_info']) return $this->error('用户信息不能为空');
//            if($data['mobile']){
//                $res = ModelUser::where('member_miniapp_id', $this->app_id)->where('mobile', $data['mobile'])->find();
//                if ($res) return $this->error('手机号已经被注册');
//            }

            $tt = new Ttlib($this->app_id);
            $res_data = $tt->code_to_token($data['code']);
            if (!$res_data['status']) return $this->error($res_data['msg']);
            //组装用户信息
            $user_info = json_decode(htmlspecialchars_decode($data['user_info']), true);//小程序返回用户信息
            $user_info['session_key'] = $res_data['data']['session_key'];
            $user_info['openid'] = $res_data['data']['openid'];
            $user_info['unionid'] = $res_data['data']['unionid'];
            $user_info['member_miniapp_id'] = $this->app_id;
            $user_info['mobile'] = $data['mobile'];
            $user_info['invite_code'] = $data['invite_code'];
            $uid = ModelUser::byteDanceReg($user_info, 'tt', true);
            if (!$uid) {
                //缺少手机号需要重新变更手机号
                if (ModelUser::getErrorCode() == 400832) return $this->code(200)->error(ModelUser::getError(), [], ModelUser::getErrorCode());
                else return $this->code(200)->error(ModelUser::getError('用户信息获取失败'));
            }
            $userInfo = ModelUser::find($uid);//得到登录用户信息
            //调用用户登录
            $rs = UserService::loginUser($userInfo, 'tt', true);
            if (!$rs['rs']) return $this->error($rs['error']);
            if (isset($data['mobile']) && $data['mobile']) Sms::clear($data['mobile'], 'bind_mobile');
            $return_data = $rs['rs'];//登录成功token信息
            $return_data['uid'] = $userInfo['id'];  //用户信息
            $return_data['invite_code'] = $userInfo['invite_code'];//获取小程序用户的邀请码
            $return_data['session_id'] = get_session_id();//返回登录session
            $return_data['open_id'] =$res_data['data']['openid'];//返回登录头条用户的openid
            return $this->success('登录成功', $return_data);
        }
        return $this->error('request method error');
    }


}